package com.example.service.Impl;

import com.example.pojo.JobDTO;
import com.example.service.JobService;
import lombok.extern.slf4j.Slf4j;
import org.quartz.*;
import org.quartz.impl.matchers.GroupMatcher;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.util.ArrayList;
import java.util.List;
import java.util.Set;

@Slf4j
@Service("jobService")
public class JobServiceImpl implements JobService {
    @Autowired
    private Scheduler scheduler;

    /**
     * 获取所有的Jobs
     * @return
     */
    @Override
    public List<JobDTO> getAllJobs() {
        // 获取所有的JobKey
        GroupMatcher<JobKey> allMatchers = GroupMatcher.anyJobGroup();
        Set<JobKey> jobKeySet = null;
        try {
            jobKeySet = scheduler.getJobKeys(allMatchers);
        } catch (SchedulerException e) {
            log.error("getAllJobs:{}", e);
        }
        return getAllJobList(jobKeySet);
    }

    /**
     * 暂停某一个特定的job
     * @param jobDTO
     * @return
     */
    @Override
    public String pauseJob(JobDTO jobDTO) {
        JobKey jobKey = JobKey.jobKey(jobDTO.getJobName(), jobDTO.getJobGroup());
        try {
            if (!scheduler.checkExists(jobKey)) {
                return NOT_EXISTS_THIS_JOB;
            }
            scheduler.pauseJob(jobKey);
        } catch (SchedulerException e) {
            log.error("pauseJob:{}", e);
            return "暂停JOB失败";
        }
        return "暂停JOB成功";
    }

    /**
     * 暂停所有的定时任务
     * @return
     */
    @Override
    public String pauseAllJobs() {
        try {
            scheduler.pauseAll();
        } catch (SchedulerException e) {
            log.error("pauseAllJobs:{}", e);
            return "全部暂停JOB失败";
        }
        return "全部暂停JOB成功";
    }

    /**
     * 恢复某一个特定的定时任务
     * @param jobDTO
     * @return
     */
    @Override
    public String resumeJob(JobDTO jobDTO) {
        JobKey jobKey = JobKey.jobKey(jobDTO.getJobName(), jobDTO.getJobGroup());
        try {
            if (!scheduler.checkExists(jobKey)) {
                return NOT_EXISTS_THIS_JOB;
            }
            scheduler.resumeJob(jobKey);
        } catch (SchedulerException e) {
            log.error("resumeJob:{}", e);
            return "恢复JOB失败";
        }
        return "恢复JOB成功";
    }

    /**
     * 恢复所有的定时任务
     * @return
     */
    @Override
    public String resumeAllJobs() {
        try {
            scheduler.resumeAll();
        } catch (SchedulerException e) {
            log.error("resumeAllJobs:{}", e);
            return "全部恢复JOB失败";
        }
        return "全部恢复JOB成功";
    }

    /**
     * 开启某一个定时任务
     * @param jobDTO
     * @return
     */
    @Override
    public String startJob(JobDTO jobDTO) {
        JobKey jobKey = JobKey.jobKey(jobDTO.getJobName(), jobDTO.getJobGroup());
        try {
            if (!scheduler.checkExists(jobKey)) {
                return NOT_EXISTS_THIS_JOB;
            }
            scheduler.triggerJob(jobKey);
        } catch (SchedulerException e) {
            log.error("startJob:{}", e);
            return "启动JOB失败";
        }
        return "启动JOB成功";
    }

    /**
     * 删除定时任务
     * @param jobDTO
     * @return
     */
    @Override
    public String deleteJob(JobDTO jobDTO) {
        JobKey jobKey = JobKey.jobKey(jobDTO.getJobName(), jobDTO.getJobGroup());
        try {
            if (!scheduler.checkExists(jobKey)) {
                return NOT_EXISTS_THIS_JOB;
            }
            scheduler.deleteJob(jobKey);
        } catch (SchedulerException e) {
            log.error("deleteJob:{}", e);
            return "删除JOB失败";
        }
        return "删除JOB成功";
    }

    @Override
    public String addJob(JobDTO jobDTO) {
        Class clazz = null;

        try {
            clazz = Class.forName(jobDTO.getJobClassName());
        } catch (ClassNotFoundException e) {
            log.error("addJob:{}", e);
            return NOT_EXISTS_THIS_JOB;
        }

        Trigger trigger = TriggerBuilder.newTrigger()
                .withIdentity(jobDTO.getTriggerName(), jobDTO.getTriggerGroup())
                .withSchedule(CronScheduleBuilder.cronSchedule(jobDTO.getCronExpression()))
                .startNow()
                .build();

        JobDetail jobDetail = JobBuilder.newJob(clazz)
                .withIdentity(jobDTO.getJobName(), jobDTO.getJobGroup())
                .build();

        try {
            scheduler.scheduleJob(jobDetail, trigger);
        } catch (SchedulerException e) {
            log.error("addJob:{}", e);
            return "添加JOB失败";
        }
        return "添加JOB成功";
    }

    @Override
    public String modifyJobTrigger(JobDTO jobDTO) {
        TriggerKey triggerKey = TriggerKey.triggerKey(jobDTO.getTriggerName(), jobDTO.getTriggerGroup());
        Trigger newTrigger = TriggerBuilder.newTrigger()
                .withIdentity(jobDTO.getTriggerName(), jobDTO.getTriggerGroup())
                .withSchedule(CronScheduleBuilder.cronSchedule(jobDTO.getCronExpression()))
                .startNow()
                .build();

        try {
            if (!scheduler.checkExists(triggerKey)) {
                return NOT_EXISTS_THIS_TRIGGER;
            }
            scheduler.rescheduleJob(triggerKey, newTrigger);
        } catch (SchedulerException e) {
            log.error("modifyJobTrigger:{}", e);
            return "更改JOB的Trigger失败";
        }
        return "更改JOB的Trigger成功";
    }

    private List<JobDTO> getAllJobList(Set<JobKey> jobKeySet) {
        List<JobDTO> jobList = new ArrayList<>();
        for (JobKey jobKey : jobKeySet) {
            JobDTO jobDTO = new JobDTO();
            setJobInfo(jobKey, jobDTO, jobList);
        }
        return jobList;
    }

    private void setJobInfo(JobKey jobKey, JobDTO jobDTO, List<JobDTO> jobDTOList) {
        JobDetail jobDetail = null;
        List<CronTrigger> triggerList = null;
        try {
            // 设置JOB信息
            jobDTO.setJobName(jobKey.getName());
            jobDTO.setJobGroup(jobKey.getGroup());
            jobDetail = scheduler.getJobDetail(jobKey);
            jobDTO.setJobDesc(jobDetail.getDescription());
            jobDTO.setJobClassName(jobDetail.getJobClass().getCanonicalName());

            // 设置trigger信息，本实例中只存在cronTrigger，同一个job可能会存在多个trigger
            triggerList = (List<CronTrigger>) scheduler.getTriggersOfJob(jobKey);
            for (CronTrigger trigger : triggerList) {
                Trigger.TriggerState triggerState = scheduler.getTriggerState(trigger.getKey());
                jobDTO.setJobStatus(triggerState.name());
                jobDTO.setCronExpression(trigger.getCronExpression());
                jobDTO.setNextFireDate(trigger.getNextFireTime());
                jobDTO.setPreviousFireDate(trigger.getPreviousFireTime());
                TriggerKey triggerKey = trigger.getKey();
                jobDTO.setTriggerName(triggerKey.getName());
                jobDTO.setTriggerGroup(triggerKey.getGroup());

                jobDTOList.add(jobDTO);
            }
        } catch (SchedulerException e) {
            log.error("setJobInfo:{}", e);
        }
    }
}